/* * This is part of Geomajas, a GIS framework, http://www.geomajas.org/. * * Copyright 2008-2015 Geosparc nv, http://www.geosparc.com/, Belgium. * * The program is available in open source according to the GNU Affero * General Public License. All contributions in this program are covered * by the Geomajas Contributors License Agreement. For full licensing * details, see LICENSE.txt in the project root. */ package org.geomajas.widget.searchandfilter.command.searchandfilter; import java.util.ArrayList; import java.util.List; import org.geomajas.command.CommandHasRequest; import org.geomajas.service.DtoConverterService; import org.geomajas.widget.searchandfilter.command.dto.GeometryUtilsRequest; import org.geomajas.widget.searchandfilter.command.dto.GeometryUtilsResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.vividsolutions.jts.geom.Geometry; /** * Command to help with common geometry manipulations. * <p> * Manipulations throw as little exceptions as possible, eg. if you give null * you get null returned, if you do not set an action, features are returned * as-is. * <p>Warning: Merge is not 100% exact, so do not use if area-size is important. * @author Kristof Heirwegh */ @Component public class GeometryUtilsCommand implements CommandHasRequest<GeometryUtilsRequest, GeometryUtilsResponse> { private final Logger log = LoggerFactory.getLogger(GeometryUtilsCommand.class); @Autowired private DtoConverterService converter; @Override public void execute(final GeometryUtilsRequest request, final GeometryUtilsResponse response) throws Exception { if (request.getGeometries() != null && request.getGeometries().length > 0) { int geomCount = request.getGeometries().length; log.debug("GeometryUtilsCommand for " + geomCount + " geometries."); if (request.getActionFlags() == 0) { response.setGeometries(request.getGeometries()); } // convert to internal Geometry[] lastResult = new Geometry[geomCount]; org.geomajas.geometry.Geometry[] dtoGeoms = request.getGeometries(); for (int i = 0; i < geomCount; i++) { lastResult[i] = converter.toInternal(dtoGeoms[i]); } List<Geometry[]> intermediateResults = new ArrayList<Geometry[]>(); // do merge before buffer if ((request.getActionFlags() & GeometryUtilsRequest.ACTION_MERGE) > 0) { lastResult = merge(lastResult); intermediateResults.add(lastResult); } if ((request.getActionFlags() & GeometryUtilsRequest.ACTION_BUFFER) > 0) { lastResult = buffer(lastResult, request.getBuffer(), request.getBufferQuadrantSegments()); intermediateResults.add(lastResult); } // -- other actions here // ---------------------------------------------------------- List<org.geomajas.geometry.Geometry> dtoResult = new ArrayList<org.geomajas.geometry.Geometry>(); if (request.isIntermediateResults()) { for (Geometry[] geometries : intermediateResults) { for (Geometry geometry : geometries) { dtoResult.add(converter.toDto(geometry)); } } } else { for (Geometry geometry : lastResult) { dtoResult.add(converter.toDto(geometry)); } } response.setGeometries(dtoResult.toArray(new org.geomajas.geometry.Geometry[dtoResult.size()])); } } private Geometry[] buffer(Geometry[] geoms, double distance, int quadrants) { Geometry[] result = new Geometry[geoms.length]; for (int i = 0; i < geoms.length; i++) { result[i] = geoms[0].buffer(distance, quadrants); } return result; } private Geometry[] merge(Geometry[] geoms) { Geometry[] result = new Geometry[1]; // points/lines to polygon, prevents problems later on... // TODO this works for meters (1 cm) what with other crs's ? Geometry merged = geoms[0].buffer(0.01); for (int i = 1; i < geoms.length; i++) { merged = merged.union(geoms[i].buffer(0.01)); } result[0] = merged; return result; } @Override public GeometryUtilsRequest getEmptyCommandRequest() { return new GeometryUtilsRequest(); } @Override public GeometryUtilsResponse getEmptyCommandResponse() { return new GeometryUtilsResponse(); } }